/**
 * 本地存储封装工具（终极版）
 * 关键保证：
 * 1. 存储键前缀一致性
 * 2. 数据读取可靠性
 * 3. 完善的错误处理
 */

const STORAGE_PREFIX = 'me_app_'; // 固定前缀（与全项目保持一致）
const MAX_DATA_SIZE = 5 * 1024 * 1024; // 5MB
const STORAGE_WARNING_THRESHOLD = 0.9; // 空间不足阈值（90%）

/**
 * 获取带前缀的完整键名
 */
const getFullKey = (key) => {
  if (!key || typeof key !== 'string') {
    throw new Error('存储键名必须是非空字符串');
  }
  return STORAGE_PREFIX + key;
};

/**
 * 获取存储数据（增强版）
 */
export const getStorage = (key, defaultValue = null) => {
  return new Promise((resolve) => {
    try {
      const fullKey = getFullKey(key);
      const value = uni.getStorageSync(fullKey);
      
      // 显式处理 undefined 和 null
      resolve(value !== undefined && value !== null ? value : defaultValue);
    } catch (error) {
      console.error(`[存储读取] 键名 "${key}" 失败:`, error);
      resolve(defaultValue); // 保证永远有返回值
    }
  });
};

/**
 * 设置存储数据（带完整验证）
 */
export const setStorage = (key, value) => {
  return new Promise((resolve) => {
    try {
      // 1. 数据大小检查
      const jsonStr = JSON.stringify(value);
      if (jsonStr.length > MAX_DATA_SIZE) {
        console.warn(`[存储拒绝] 键名 "${key}" 数据过大: ${jsonStr.length} bytes`);
        resolve(false);
        return;
      }

      // 2. 实际写入
      const fullKey = getFullKey(key);
      uni.setStorageSync(fullKey, value);
      
      // 3. 写入验证
      const readBack = uni.getStorageSync(fullKey);
      if (JSON.stringify(readBack) !== jsonStr) {
        throw new Error('写入验证失败：读取值与写入值不一致');
      }
      
      resolve(true);
    } catch (error) {
      console.error(`[存储写入] 键名 "${key}" 失败:`, error);
      resolve(false);
    }
  });
};

/**
 * 移除存储数据
 */
export const removeStorage = (key) => {
  return new Promise((resolve) => {
    try {
      const fullKey = getFullKey(key);
      uni.removeStorageSync(fullKey);
      resolve(true);
    } catch (error) {
      console.error(`[存储删除] 键名 "${key}" 失败:`, error);
      resolve(false);
    }
  });
};

/**
 * 清空应用相关存储
 */
export const clearAppStorage = () => {
  return new Promise((resolve) => {
    try {
      const res = uni.getStorageInfoSync();
      let successCount = 0;
      
      res.keys.forEach(key => {
        if (key.startsWith(STORAGE_PREFIX)) {
          try {
            uni.removeStorageSync(key);
            successCount++;
          } catch (e) {
            console.warn(`[清理跳过] 键名 "${key}" 删除失败:`, e);
          }
        }
      });
      
      console.log(`[存储清理] 成功删除 ${successCount} 项`);
      resolve(successCount > 0 || res.keys.length === 0);
    } catch (error) {
      console.error('[存储清理] 全局失败:', error);
      resolve(false);
    }
  });
};

/**
 * 获取存储大小信息
 */
export const getStorageSize = () => {
  return new Promise((resolve) => {
    try {
      const res = uni.getStorageInfoSync();
      resolve({
        currentSize: res.currentSize,
        limitSize: res.limitSize,
        keys: res.keys || []
      });
    } catch (error) {
      console.error('[存储大小] 获取失败:', error);
      resolve({ currentSize: 0, limitSize: 0, keys: [] });
    }
  });
};

// ============ 备份相关增强功能 ============

/**
 * 严格验证备份数据
 */
export const validateBackupData = (data) => {
  if (typeof data !== 'object' || data === null) {
    console.error('[备份验证] 数据必须是非空对象');
    return false;
  }

  // 验证所有键都带有正确前缀
  const isValid = Object.keys(data).every(key => {
    const isValidKey = key.startsWith(STORAGE_PREFIX);
    if (!isValidKey) {
      console.warn(`[备份验证] 无效键名: ${key}`);
    }
    return isValidKey;
  });

  if (!isValid) {
    console.error('[备份验证] 存在无效键名（前缀不匹配）');
    return false;
  }

  // 检查核心模块是否存在
  const requiredModules = ['home', 'plan', 'cognition'].map(m => STORAGE_PREFIX + m);
  const hasAllModules = requiredModules.every(m => m in data);
  
  if (!hasAllModules) {
    console.error('[备份验证] 缺少核心模块数据');
  }

  return hasAllModules;
};

/**
 * 增强版空间检查
 */
export const checkStorageSpace = async (requiredSize = 0) => {
  try {
    const { currentSize, limitSize, keys } = await getStorageSize();
    const remainingSpace = limitSize - currentSize;
    const isEnough = remainingSpace > requiredSize;

    // 空间不足提醒
    if (currentSize / limitSize > STORAGE_WARNING_THRESHOLD) {
      uni.showToast({
        title: `存储空间不足 (${(currentSize / 1024 / 1024).toFixed(1)}MB/${(limitSize / 1024 / 1024).toFixed(1)}MB)`,
        icon: 'none',
        duration: 3000
      });
    }

    return { 
      isEnough, 
      currentSize, 
      limitSize,
      usedPercentage: (currentSize / limitSize * 100).toFixed(1) + '%',
      remainingSpace,
      totalKeys: keys.length
    };
  } catch (error) {
    console.error('[空间检查] 失败:', error);
    return { isEnough: false, currentSize: 0, limitSize: 0 };
  }
};

/**
 * 安全恢复数据（终极版）
 */
export const safeRestore = async (backupData) => {
  // 深度校验
  if (!validateBackupData(backupData)) {
    return { success: false, message: '备份数据校验失败（格式/前缀不匹配）' };
  }

  // 精确空间检查
  try {
    const backupSize = new Blob([JSON.stringify(backupData)]).size;
    const { isEnough, remainingSpace } = await checkStorageSpace(backupSize);
    
    if (!isEnough) {
      return { 
        success: false, 
        message: `需要 ${(backupSize / 1024 / 1024).toFixed(2)}MB 空间，当前仅剩 ${(remainingSpace / 1024 / 1024).toFixed(2)}MB` 
      };
    }

    // 分步恢复（带进度跟踪）
    const keys = Object.keys(backupData);
    let restoredCount = 0;
    
    for (const key of keys) {
      try {
        await setStorage(key.replace(STORAGE_PREFIX, ''), backupData[key]);
        restoredCount++;
      } catch (error) {
        console.error(`[恢复失败] 键名 ${key}:`, error);
        // 继续恢复其他项
      }
    }

    return {
      success: restoredCount === keys.length,
      message: restoredCount === keys.length 
        ? '完全恢复成功' 
        : `部分恢复成功 (${restoredCount}/${keys.length})`,
      restoredCount,
      totalCount: keys.length
    };
  } catch (error) {
    console.error('[恢复过程] 全局失败:', error);
    return { success: false, message: `恢复过程崩溃: ${error.message}` };
  }
};

export default {
  getStorage,
  setStorage,
  removeStorage,
  clearAppStorage,
  getStorageSize,
  validateBackupData,
  checkStorageSpace,
  safeRestore,
  STORAGE_PREFIX // 显式导出前缀供外部校验
};